﻿namespace Skymate.Commands
{
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Linq;

    using Skymate.Lyjt.Core;

    /// <summary>
    /// TODO:针对属性进行验证
    /// </summary>
    public class Phase
    {
        public const int BufferLength = 24;

        /// <summary>
        /// 相位号 
        /// </summary>
        [Category("信息"), Description("相位号"), DisplayName(@"相位号")]
        public int Number { get; set; }
        
        [Category("信息"), Description("灯色"), DisplayName(@"灯色")]
        public List<LightColor> LightColors { get; set; } = new List<LightColor>();

        /// <summary>
        /// 插入相位时间
        /// </summary>
        [Category("信息"), Description("插入相位时间"), DisplayName(@"插入相位时间")]
        public int Time { get; set; }

        /// <summary>
        /// 最小率
        /// </summary>
        [Category("信息"), Description("最小绿"), DisplayName(@"最小绿")]
        public int MinGreen { get; set; }

        /// <summary>
        /// 最大率
        /// </summary>
        [Category("信息"), Description("最大绿"), DisplayName(@"最大绿")]
        public int MaxGreen { get; set; }

        /// <summary>
        /// 机动车绿闪时间
        /// </summary>
        [Category("信息"), Description("机动车绿闪"), DisplayName(@"机动车绿闪")]
        public int GreenFlash { get; set; }

        /// <summary>
        /// 黄灯时间取值范围  3~5
        /// </summary>
        [Category("信息"), Description("黄灯时间取值"), DisplayName(@"黄灯时间取值")]
        public int YellowRange { get; set; }

        /// <summary>
        /// 红灯时间取值范围  0~6
        /// </summary>
        [Category("信息"), Description("红灯时间取值"), DisplayName(@"红灯时间取值")]
        public int RedRange { get;  set; }

        /// <summary>
        /// 行人闪烁时间 大于0，小于相位长度 -  红灯时间
        /// </summary>
        [Category("信息"), Description("行人闪烁时间"), DisplayName(@"行人闪烁时间")]
        public int PedestriansFlashing { get; set; }

        /// <summary>
        /// 行人闪烁方式
        /// </summary>
        [Category("信息"), Description("行人闪烁方式"), DisplayName(@"行人闪烁方式")]
        public int PedestriansFlashingType { get; set; }

        /// <summary>
        /// 行人提前亮时间固定提前一个红灯时间
        /// </summary>
        [Category("信息"), Description("行人提前亮时间"), DisplayName(@"行人提前亮时间")]
        public int ForwardPedestrians { get; set; }

        /// <summary>
        /// 红灯结束闪烁时间 ,小于等于 黄灯+红灯时间，最小值为红灯时间，0为不闪烁
        /// </summary>
        [Category("信息"), Description("红灯结束闪烁时间"), DisplayName(@"红灯结束闪烁时间")]
        public int RedLightOverTime { get; set; }

        /// <summary>
        /// 校验和
        /// </summary>
        [Category("信息"), Description("校验码"), DisplayName(@"校验码"),ReadOnly(true)]
        public int Checksum { get; set; }
        
        public static Phase CreatePhase(byte[] buffer)
        {
            if (buffer.Length != BufferLength)
            {
                return null;
            }

            Phase result = new Phase { Number = buffer[0], Time = buffer[1] };
            
            // 3~14 是灯色状态
            var colorsBuffer = buffer.Range(2, 12);
            result.LightColors = LightColorState.Create(colorsBuffer)
                .LightColors.ToList();

            result.MinGreen = buffer[14];
            result.MaxGreen = buffer[15];

            // 机动车绿闪时间 ，小于 minGreen,否则取 minGreen-1,0表示无
            result.GreenFlash = buffer[16];

            // 黄灯时间取值范围  3~5
            result.YellowRange = buffer[17];

            // 红灯时间取值范围  0~6
            result.RedRange = buffer[18];

            // 行人闪烁时间 大于0，小于相位长度 -  红灯时间
            result.PedestriansFlashing = buffer[19];

            // 行人闪烁方式
            result.PedestriansFlashingType = buffer[20];

            // 行人提前亮时间固定提前一个红灯时间
            result.ForwardPedestrians = buffer[21];

            // 红灯结束闪烁时间 ,小于等于 黄灯+红灯时间，最小值未红灯时间，0为不闪烁
            result.RedLightOverTime = buffer[22];

            // 校验和
            result.Checksum = buffer[23];

            return result;
        }

        public string[] ToStrings()
        {
            IList<string> result = new List<string>();

            result.Add(this.Number.ToString());
            result.Add(this.Time.ToString());
            result.Add(this.MinGreen.ToString());
            result.Add(this.MaxGreen.ToString());
            result.Add(this.GreenFlash.ToString());

            result.Add(this.YellowRange.ToString());
            result.Add(this.RedRange.ToString());
            result.Add(this.PedestriansFlashing.ToString());
            result.Add(this.PedestriansFlashingType.ToString());
            result.Add(this.ForwardPedestrians.ToString());

            result.Add(this.RedLightOverTime.ToString());
            result.Add(this.Checksum.ToString());

            return result.ToArray();
        }
        
        public byte[] ToBuffer()
        {
            byte[] buffer = new byte[24];

            buffer[0] = (byte)this.Number;
             
            buffer[1] = (byte)this.Time;
            
            // 3~14 是灯色状态

            var colors=new List<LightColor>();
            colors.AddRange(this.LightColors);
            if (this.LightColors.Count<48)
            {
                for (var i = this.LightColors.Count; i < 48 ; i++)
                {
                    colors.Add(LightColor.Destroy);
                }    
            }

            for (var i = 0; i < colors.Count; )
            {
                var b = LightColorHelper.CreateLightColorByte(colors[i], colors[i + 1], colors[i + 2], colors[i + 3]);
                buffer[2 + ((i)/4)] = b;
                i += 4;
            }
            
            buffer[14]= (byte)this.MinGreen;
            buffer[15]= (byte)this.MaxGreen;

            // 机动车绿闪时间 ，小于 minGreen,否则取 minGreen-1,0表示无
            buffer[16]= (byte)this.GreenFlash ;

            // 黄灯时间取值范围  3~5
            buffer[17]= (byte)this.YellowRange ;

            // 红灯时间取值范围  0~6
            buffer[18]= (byte)this.RedRange ;

            // 行人闪烁时间 大于0，小于相位长度 -  红灯时间
            buffer[19]= (byte)this.PedestriansFlashing  ;

            // 行人闪烁方式
            buffer[20]= (byte)this.PedestriansFlashingType ;

            // 行人提前亮时间固定提前一个红灯时间
            buffer[21]= (byte)this.ForwardPedestrians ;

            // 红灯结束闪烁时间 ,小于等于 黄灯+红灯时间，最小值未红灯时间，0为不闪烁
            buffer[22]= (byte)this.RedLightOverTime  ;
            
            var checksum = this.CalculateChecksum(buffer.Range(0, 23));
            
            // 校验和
            buffer[23] = checksum;

            return buffer;
        }

        private byte CalculateChecksum(byte[] buffer)
        {
            return buffer.Aggregate<byte, byte>(0x00, (current, b) => (byte)(current + b));
        }
    }

}